<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        li {
            list-style: none;
            line-height: 40px;
            border: 1px dashed #333;
        }

        .wrap {
            margin-bottom: 40px;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- watch监听数组 -->
        <!-- <div class="wrap">
            <p>list:{{list}}</p>
            <p>
                <button @click="addEle">新增元素</button>
                <button @click="delEle">删除元素</button>
                <button @click="editEle">修改元素</button>
            </p>
        </div> -->

        <!-- watch监听对象 -->
        <p>
            zhang: {{zhang.name}}---{{zhang.age}}
        </p>
        <p>
            <button @click="zhang={name:'小六子',age:22}">覆盖</button>
            <button @click="zhang.name='李四'">changeName</button>
            <button @click="zhang.age++">changeAge</button>
        </p>
    </div>
</body>
<script>
    /* 
        watch 侦听器, 监听data/computed上的数据改变,并执行一系列副作用操作!! (当前数据改变后可能造成的影响)
            作用:
            1. 可以检测数据改变
            2. 数据改变后可以做一些其他处理

        如何使用watch:
            在new Vue(option)的配置对象中新增watch属性,属性值也是一个对象
            1. 对象的键名: 就是要监听的属性名 (data/computed)
            2. 对象的键值: 数据改变后要执行的回调函数,回调函数有两个参数(newVal,oldVal),分别表示新值和旧值  


        watch小结:
            1. watch更注重自身改变,对其他数据造成的影响(可以执行一系列副作用操作)
            2. watch可以支持异步操作
            3. watch监听数据时是惰性的, watch在初始化渲染结果并不会立即执行, 而是等数据改变之后才会执行


        对比Vue响应式和watch侦听器
            1. Vue响应式是在new Vue(option)创建过程中 通过给数据(data / computed)配置Object.defineProperty(vue2)/Proxy(Vue3) 以到达检测数据改变, 更新视图的目的  

            2. watch侦听器 是用户在使用Vue过程中, 根据自己监听数据的需要,绑定的侦听器, 当数据改变时,会执行对应的回调函数  

        watch监听数组和对象: 
            (1) watch监听数组时,无法检测数据一下变化
                当你利用索引直接设置一个数组项时，例如：vm.items[indexOfItem] = newValue
                当你修改数组的长度时，例如：vm.items.length = newLength

                !!!!!
            (2) watch监听对象时, 默认是浅层的 (如果监听的数据时一个对象,默认只监听该属性的值是否发生改变,  如果对该对象下的某个属性进行修改,无法被watch监听到 =>)
                解决方法: 可以开启深度监听 

                新的问题: 开启深度监听之后,newVal和oldVal引用同一片内存地址 => 最终都是新值



    */
    var vm = new Vue({
        el: "#app",
        data: {
            list: [1, 4, 7, 2, 5, 8, 3, 6, 9],
            zhang: { name: "张三", age:18 },
        },
        methods: {
            addEle() {
                var ele = Math.round(Math.random() * 100); // 随机元素
                this.list.push(ele);
            },
            delEle() {
                var index = Math.floor(Math.random() * this.list.length);
                this.list.splice(index, 1);
            },
            editEle(){
                // this.list[1] = 44;
                // this.list.splice(1,1,44);

                this.list.length --;
                this.$forceUpdate();
            }
        },
        watch: { // 配置侦听器(对象)
            list:function(newVal){
                console.log("list发送改变",newVal);
            },

            // watch监听对象时, 默认是浅层的
            // zhang:function(newVal){
            //     console.log("zhang改变了",newVal);
            // }

            // watch开启深度监听
            zhang:{
                handler:function(newVal,oldVal){ // 处理函数
                    // console.log("zhang改变了",newVal,oldVal);
                    console.log("zhang改变了",JSON.stringify(newVal),JSON.stringify(oldVal));
                },
                deep:true, // 是否开启深度监听
            }


        }

    })



</script>

</html>